/**
 * 异步请求的一个场景
 * 下一个请求依赖于上一个请求的结果
 */
function getData(param) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(param)
    }, 500)
  })
}

/**
 * 方案1： 会产生回调地狱
 */
// getData('aaa').then((res) => {
//   getData(res + 'bbb').then((res) => {
//     getData(res + 'ccc').then((res) => {
//       console.log(res)
//     })
//   })
// })

/**
 * 方案2：返回一个Promise，链式调用
 */
// getData('aaa')
//   .then((res) => {
//     //返回一个promise
//     return getData(res + 'bbb')
//   })
//   .then((res) => {
//     return getData(res + 'ccc')
//   })
//   .then((res) => {
//     console.log(res)
//   })

/**
 * 方案3：利用Promise和generator
 */
function* requestData() {
  const res1 = yield getData('aaa')
  const res2 = yield getData(res1 + 'bbb')
  const res3 = yield getData(res2 + 'ccc')
  console.log(res3)
}

//手动执行生成器函数
const generator = requestData()
//generator.next()获取到的是一个{done: false, value: 一个Promise}
generator.next().value.then((res) => {
  console.log(res) //aaa
  //此处next(res)相当于将 'aaa' 赋值给res1，即：
  //const res2 = yield getData('aaa'+'bbb')
  generator.next(res).value.then((res) => {
    //此处next(res)相当于将 'aaa'+'bbb' 赋值给res2，即：
    //const res3 = yield getData('aaa'+'bbb'+'ccc')
    generator.next(res).value.then((res) => {
      //将res赋值给res3的，即 'aaabbbccc'
      generator.next(res)
    })
  })
})

/**
 * 自动执行生成器函数
 * @param genFn 生成器函数
 */
function execGenerator(genFn) {
  const generator = genFn()

  function exec(res) {
    const result = generator.next(res)
    if (result.done) {
      //{done: true, value: undefined}
      return result.value
    }
    result.value.then((res) => {
      exec(res)
    })
  }

  exec()
}

execGenerator(requestData) //

//使用TJ大神的co库函数
const co = require('co')
co(requestData)

/**
 * 方案4：async/await (ES8新增的关键字)
 * 对照生成器函数其实是一个语法糖
 */
//function* requestData() {
//   const res1 = yield getData('aaa')
//   const res2 = yield getData(res1 + 'bbb')
//   const res3 = yield getData(res2 + 'ccc')
//   console.log(res3)
// }
async function reqData() {
  const res1 = await getData('aaa')
  const res2 = await getData(res1 + 'bbb')
  const res3 = await getData(res2 + 'ccc')
  console.log('--------')
  console.log(res3)
}

reqData()
